﻿// 注释

using GeneralCommon.Models.SignalR;
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Admin.EcsWeb.Service.Remote;
public class SignalRService : ISignalRService
{
    public static SignalRService Instance { get; private set; }

    private User _user;
    private HubConnection connection;
    public event EventHandler<string> ClosedEvent;
    public event EventHandler<string> ConnectedEvent;
    public event EventHandler<InformModel> MessageEvent;
    public event EventHandler<RemoteLog> RemoteLogEvent;
    private List<string> subcribles = new List<string>();

    public SignalRService()
    {
        Instance = this;
    }
    public bool IsConnected { get; set; }
    /// <summary>
    /// 连接服务
    /// </summary>
    /// <param name="url"></param>
    /// <param name="user"></param>
    /// <returns></returns>
    public async Task<bool> ConnectServer(string url, User user)
    {

        try
        {
            await StopServer();
            if (connection != null && connection.State == HubConnectionState.Connecting)
            {
                return false;
            }
            if (connection == null || connection.State != HubConnectionState.Connected)
            {
                _user = user;
                connection = new HubConnectionBuilder()
          .WithUrl($"{url}/MessageHub", options =>
          {
              options.AccessTokenProvider = async () => await Task.FromResult($"{user.ID}*{user.Name}*{user.Type}");
          }).WithAutomaticReconnect()
          .Build();
                // 连接signalR
                await connection.StartAsync();
                connection.On("GetUser", async () =>
                {
                    await connection.InvokeAsync<List<User>>("Login",
                   _user);
                });

                connection.Closed += Connection_Closed;
                connection.Reconnecting += (e) =>
                {
                    IsConnected = false;
                    return Task.CompletedTask;
                };
                connection.Reconnected += e =>
                {
                    IsConnected = true;
                    ConnectedEvent?.Invoke(connection, "");


                    return Task.CompletedTask;
                };
            }
            subcribles.Clear();
            var users = await connection.InvokeAsync<List<User>>("Login",
                   user);
            ConnectedEvent?.Invoke(connection, "");
            IsConnected = true;
            return true;
        }
        catch (Exception ex)
        {
            ClosedEvent?.Invoke(connection, ex.Message);
            return false;
        }

    }



    /// <summary>
    /// 停止服务
    /// </summary>
    /// <returns></returns>
    public async Task<bool> StopServer()
    {
        try
        {
            if (connection == null)
            {
                return false;
            }

            IsConnected = false;

            subcribles.Clear();

            await connection.StopAsync();

            await connection.DisposeAsync();



            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    /// <summary>
    /// 关闭连接
    /// </summary>
    /// <param name="arg"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private Task Connection_Closed(Exception arg)
    {

        //await Task.Delay(new Random().Next(0, 5) * 1000);
        //await connection.StartAsync();
        // 目前不作处理，手动调用
        IsConnected = false;
        subcribles.Clear();
        ClosedEvent?.Invoke(connection, arg.Message);
        return Task.CompletedTask;
    }

    /// <summary>
    /// 监听信息
    /// </summary>
    /// <returns></returns>
    public bool ListenMessage()
    {
        try
        {
            if (subcribles.Contains("InformMessage"))
            {
                return true;
            }
            if (connection == null || connection.State != HubConnectionState.Connected)
            {
                return false;
            }
            if (MessageEvent == null) return false;

            connection.On<InformModel>("InformMessage", (inform) =>
            {
                MessageEvent?.Invoke(connection, inform);
            });
            subcribles.Add("InformMessage");
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    /// <summary>
    /// 监听远程日志
    /// </summary>
    /// <returns></returns>
    public bool ListenRemoteLog()
    {
        try
        {
            if (subcribles.Contains("ReadLog"))
            {
                return true;
            }
            if (connection == null || connection.State != HubConnectionState.Connected)
            {
                return false;
            }
            if (RemoteLogEvent == null) return false;
            connection.On<RemoteLog>("ReadLog", (log) =>
            {
                RemoteLogEvent?.Invoke(connection, log);
            });
            subcribles.Add("ReadLog");
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
    /// <summary>
    /// 写日志
    /// </summary>
    /// <param name="log"></param>
    /// <returns></returns>
    public async Task<bool> WriteLog(RemoteLog log)
    {
        try
        {
            if (connection == null || connection.State != HubConnectionState.Connected)
            {
                return false;
            }
            await connection.InvokeAsync("WriteLog",
                       log);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    /// <summary>
    /// 写信息
    /// </summary>
    /// <param name="log"></param>
    /// <returns></returns>
    public async Task<bool> WriteMessage(InformModel log)
    {
        try
        {
            if (connection == null || connection.State != HubConnectionState.Connected)
            {
                return false;
            }
            await connection.InvokeAsync("WriteMessage",
                       log);
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
}
